#ifndef TOOLUTILS_H
#define TOOLUTILS_H

#include <QObject>
#include <QMessageBox>

#include "dragabletab.h"


/*
    继承了 QObject GUI类
    整体功能:
        整体工具类
    具体功能：
        1、ID3文件的解析，目前解析音乐名、歌手名、专辑名、专辑图片等
        2、messageBox提示窗封装，并提供接口
        3、文件相关操作(打开、保存、另存为)
        4、Qss文件的读取
        5、通过QMimeDatabase进行文件类型的判断
        6、图片高斯模糊接口
        7、检测当前鼠标位置是否在窗口上(目前用于判断是否需要悬浮窗口)
        8、平移动画显示控件(TODO：可以封装很多动画)
*/

class ToolUtils : public QObject
{
    Q_OBJECT
    struct ID3Header
    {
        char magic[3];  // 文件头，必须为ID3
        char ver;       // 版本号，3=v2.3，4=v2.4
        char rev;       // 副版本号，为0
        char flags;     // 标识位，只使用高4位
        char size[4];   // 标签长度，每个字节只使用低7位，拼接得到28位长度
    };

    struct ID3Flags
    {
        unsigned unsynchronisation : 1; // 一个bit位
        unsigned extendedHeader : 1;
        unsigned experimentalIndicator : 1;
        unsigned footerPresent : 1;
    };

    struct ID3_23ExtendedHeader {
        char size[4];
        char extendedFlags[2];
        char padding[4];
    };

    struct ID3_24ExtendedHeader {
        char size[4];
        char flagNumbers;
        char extendedFlags;
    };

    struct ID3Frame {
        char frameId[4]; // 帧id
        char size[4];   // 帧长度
        char flags[2];  // 两字节标志位 (相关状态, 编码目的)
    };

    struct ID3FrameFlags
    {
        unsigned isTagAlterDiscard : 1;
        unsigned isFileAlterDiscard : 1;
        unsigned isReadOnly : 1;
        unsigned isGroupInformation : 1;
        unsigned isCompressed : 1;
        unsigned isEncrypted : 1;
        unsigned isUnsyrchronised : 1;
        unsigned hasDataLengthIndicator : 1;
    };

public:
    ToolUtils();

    class Worker final : public QObject
    {
    public:
        explicit Worker(QObject *parent)
            : QObject(parent) {}
        ~Worker() override;

        template<typename Func>
        void DoWork(Func& func) const {
            func();
        }
    };

    static bool EasyDialogReturnBool(const QString& title, const QString& text);
    static std::pair<DragableTab*, QWidget*> OpenPage(QWidget* parentWidget);
    static bool SavePage(std::pair<DragableTab*, QWidget*> page, QWidget* parentWidget);
    static bool SavePageAs(std::pair<DragableTab*, QWidget*> page, QWidget* parentWidget);
    static QString ReadStyleSheet(QString qrcPath);
    static QString CheckFileType(QString filePath);
    static QMap<QString, QByteArray> ExtractInfoFromMP3(const QString& mp3Path);
    static QImage GaussianBlur(const QImage &src, int radius, double sigma);
    static bool IsCursorInWindow();
    static void ShowMoveAnimation(QWidget* widget, const QPoint& startPos, const QPoint& endPos, int duration);

private:
    static inline bool ValidateID3Header(const ID3Header& header);
    static inline ID3Flags ExtractID3HeaderFlags(const ID3Header& header);
    static inline unsigned int ConvertSynchsafeIntgerToInt(const char synchsafeIntger[4]);
    static inline unsigned int ConvertCharsToInt(const char chars[]);
    static inline ID3FrameFlags ExtractID3FrameFlags(const ID3Frame& frame);
    static QByteArray ParseTextFromFrameData(char encoding, const QByteArray& frameData);
    static QByteArray ExtractPictureFromData(char encoding, const QByteArray& frameData);
    static int GetTextLength(char encoding, const QByteArray& text);
};

#endif // TOOLUTILS_H
